#coding=utf-8

import logging
# DeadlineExceededError can live in two different places
try:
  # When deployed
  from google.appengine.runtime import DeadlineExceededError
except ImportError:
  # In the development server
  from google.appengine.runtime.apiproxy_errors import DeadlineExceededError

from google.appengine.api import users
from google.appengine.api import memcache

import datetime

from models import *
from framework.controller import *

from utils import page

### Decorators for request handlers ###
def login_required(func):
  """Decorator that redirects to the login page if you're not logged in."""
  def login_wrapper(self, *args, **kwds):
    if not self.get_account().is_sign_in:
      self.handler.redirect(users.create_login_url(self.request.path))
    return func(self, *args, **kwds)
  return login_wrapper

def admin_required(func):
  def admin_wrapper(self, *args, **kwds):
    """Decorator that insists that you're logged in as administratior."""
    if not self.get_account().is_sign_in:
      self.handler.redirect(users.create_login_url(self.request.path))
    if not self.get_account().is_admin:
      self.render('admin-required')
      return None
    return func(self, *args, **kwds)
  return admin_wrapper
#######################################################

CACHE_KEY_FIRST_PAGE = 'first_page_content'

class IndexController(BaseController):
    def index(self, kwds = None):
        content = memcache.get(CACHE_KEY_FIRST_PAGE)
        if content is None:
            current_page = Entry.get_page(1)
            tags = Tag.all_entry_tags().fetch(page.DEFAULT_PAGE_SIZE)
            content = self.get_response_content('index', {'page' : current_page, 'tags': tags})
            memcache.set(CACHE_KEY_FIRST_PAGE, content)
        self.render_content(content)

class EntryController(BaseController):
    def index(self, kwds = None):
        if kwds != None and len(kwds) > 0:
            tag_kn = kwds['tag_key_name']
            tag = Tag.get_by_key_name(tag_kn)
            entries = {}
            if tag is not None:
                entries = tag.entries;
            return self.render('frag/entries-for-tag', {'entries' : entries, 
                                                        'tag'    :  tag})
        else:
            page_index = int(self.request.get('page'), 10)
            current_page = Entry.get_page(page_index)
            tags = Tag.all_entry_tags().fetch(page.DEFAULT_PAGE_SIZE)
            format = self.request.get('format')
            if format == 'atom':
                self.render('feed', {'page' : current_page})
            else:
                self.render('index', {'page' : current_page, 'tags' : tags})
    def show(self, id, kwds = None):
        entry = Entry.get_by_id(long(id))
        if entry is not None:
            return self.render("entry", {'entry' : entry})
        return self.render('error')
    
    @admin_required
    def edit_new(self, kwds = None):
        tags = Tag.all_entry_tags().fetch(page.DEFAULT_PAGE_SIZE)
        self.render('entry-form', {'tags' : tags})
    @admin_required
    def edit(self, id, kwds = None):
        entry = Entry.get_by_id(long(id))
        if entry is None:
            return self.render('error')
        tags = Tag.all_entry_tags().fetch(page.DEFAULT_PAGE_SIZE)
        self.render('entry-form', {'id' : id, 'entry' : entry, 'tags' : tags})
    @admin_required
    def create(self, kwds = None):
        entry = Entry()
        self._bind_entry(self.request, entry)
        entry.create()
        memcache.delete(CACHE_KEY_FIRST_PAGE)
        self.render_json({'msg':'OK'})
    @admin_required
    def update(self, id, kwds = None):
        entry = Entry.get_by_id(long(id))
        if entry is None:
            self.render_json({'msg' : 'ERROR'})
        else:
            f = self.request.get('from')
            o = self.request.get('operation')
            if f == 'admin' and o == 'approve':
                entry.approve()
                self.render_json({'msg' : 'OK'})
            else:
                self._bind_entry(self.request, entry) 
                entry.update()
                memcache.delete(CACHE_KEY_FIRST_PAGE)
                self.render_json({'msg' : 'OK'})
    @admin_required
    def destroy(self, id):
        entry = Entry.get_by_id(long(id))
        if entry is None:
            self.render_json({'msg' : 'ERROR'})
        else:
            entry.remove()
            memcache.delete(page.CACHE_KEY_FIRST_PAGE)
            return self.render_json({'msg' : 'OK'})
    def _bind_entry(self, request, entry):
        validate_result = {}
        entry.title       = request.get('title')
        logging.debug('entry title: ' + entry.title)
        entry.text        = request.get('text')
        entry.tags_as_string = request.get('tags')
        entry.author      = self.get_account().email

class TagController(BaseController):
    def index(self, kwds = None):
        tags = Tag.all_entry_tags().fetch(page.DEFAULT_PAGE_SIZE)
        self.render('frag/entry-tags', {'tags' : tags})

class CommentController(BaseController):
    def create(self, kwds):
        entry_id = kwds['entry_id']
        entry = Entry.get_by_id(entry_id)
        comment = Comment(weblog_entry = entry)
        self._bind_comment(self.request, comment);
        comment.create()
        self.render_json({'msg':'OK'})
    @admin_required
    def destroy(self, id):
        tag = Tag.get_by_id(long(id))
        if entry is None:
            self.render_json({'msg' : 'ERROR'})
        else:
            tag.remove()
            memcache.delete(page.CACHE_KEY_FIRST_PAGE)
            return self.render_json({'msg' : 'OK'})
    def _bind_comment(self, request, comment):
        comment.email   = request.get('email') or ''
        comment.content = request.get('content')
        comment.link    = request.get('link') or ''
        comment.author  = self.get_account().email

class ArchiveController(BaseController):
    def index(self, kwds):
        page_index = self.request.get('page') or 1
        entries = Entry.get_page(page_index, 20)
        self.render('archive', {"entries" : entries})

class AtomController(BaseController):
    def index(self, kwds):
        entries = Entry.get_feed_entries()
        if entries and entries[0]:
            last_updated = entries[0].local_put_time
        else:
            last_updated = util.get_local_time(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')
        self.response.headers['Content-Type'] = 'application/atom+xml'
        self.render('atom', {'entries': entries, 'last_updated': last_updated })
        
class ErrorController(BaseController):
    def index(self, kwds = None):
        self.render('error') 